package com.adk.backend.config;

import com.adk.backend.annotation.RequiresPermission;
import com.adk.backend.common.Result;
import com.adk.backend.service.PermissionService;
import com.adk.backend.util.JwtUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * 权限拦截器
 */
@Slf4j
@Component
public class PermissionInterceptor implements HandlerInterceptor {
    
    @Autowired
    private JwtUtil jwtUtil;
    
    @Autowired
    private PermissionService permissionService;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 只处理方法级别的请求
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        
        // 检查是否有权限注解
        RequiresPermission permission = method.getAnnotation(RequiresPermission.class);
        if (permission == null) {
            // 检查类级别注解
            permission = handlerMethod.getBeanType().getAnnotation(RequiresPermission.class);
        }
        
        // 如果没有权限注解，直接放行
        if (permission == null) {
            return true;
        }
        
        // 获取Token
        String token = getTokenFromRequest(request);
        if (!StringUtils.hasText(token)) {
            writeErrorResponse(response, "未登录或Token已过期");
            return false;
        }
        
        // 验证Token并获取用户类型
        Integer userType = getUserTypeFromToken(token);
        if (userType == null) {
            writeErrorResponse(response, "Token无效");
            return false;
        }
        
        // 检查权限
        boolean hasPermission = checkPermission(permission, userType);
        if (!hasPermission) {
            writeErrorResponse(response, "没有访问权限");
            return false;
        }
        
        return true;
    }
    
    /**
     * 从请求中获取Token
     */
    private String getTokenFromRequest(HttpServletRequest request) {
        String authHeader = request.getHeader("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7);
        }
        return null;
    }
    
    /**
     * 从Token中获取用户类型
     */
    private Integer getUserTypeFromToken(String token) {
        try {
            io.jsonwebtoken.Claims claims = jwtUtil.getClaimsFromToken(token);
            if (claims != null) {
                Object userTypeObj = claims.get("userType");
                if (userTypeObj != null) {
                    return Integer.valueOf(userTypeObj.toString());
                }
            }
        } catch (Exception e) {
            log.error("从Token获取用户类型失败", e);
        }
        return null;
    }
    
    /**
     * 检查权限
     */
    private boolean checkPermission(RequiresPermission permission, Integer userType) {
        // 检查单个权限
        if (StringUtils.hasText(permission.value())) {
            return permissionService.hasPermission(userType, permission.value());
        }
        
        // 检查多个权限
        if (permission.any().length > 0) {
            if (permission.requireAll()) {
                // 需要所有权限
                for (String flagAct : permission.any()) {
                    if (!permissionService.hasPermission(userType, flagAct)) {
                        return false;
                    }
                }
                return true;
            } else {
                // 满足任意一个权限即可
                for (String flagAct : permission.any()) {
                    if (permissionService.hasPermission(userType, flagAct)) {
                        return true;
                    }
                }
                return false;
            }
        }
        
        return false;
    }
    
    /**
     * 写入错误响应
     */
    private void writeErrorResponse(HttpServletResponse response, String message) throws IOException {
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setContentType("application/json;charset=UTF-8");
        Result<Object> result = Result.error(message);
        response.getWriter().write(objectMapper.writeValueAsString(result));
    }
}

